package com.gitee.l0km.beanfilter.core.context;

import java.util.Objects;

import com.gitee.l0km.beanfilter.core.CodecScene;
import com.gitee.l0km.beanfilter.core.RequestPhase;

/**
 * 由序列化器和反序列化器提供的过滤器上下文
 * @author guyadong
 *
 */
public class LocalContext {
	private static final Object NULL_OBJECT = new Object();
	private final Object bean;
	private final RequestPhase requestPhase;
	private final CodecScene scene;
	private LocalContext() {
		this(null, RequestPhase.UNKNOWN, CodecScene.UNKNOWN);
	}
	private LocalContext(Object bean, RequestPhase requestPhase, CodecScene scene) {
		this.bean = bean;
		this.requestPhase = requestPhase;
		this.scene = scene;
	}
	/**
	 * <ul>
	 * <li>序列化阶段({@link RequestPhase#SERIALIZING} )返回当前序列化对象</li>
	 * <li>反序列化阶段({@link RequestPhase#DESERIALIZING} )返回{@code null}</li>
	 * </ul>
	 */
	public Object getBean() {
		return bean == NULL_OBJECT ? null : bean;
	}
	/**
	 * 返回当前的过滤器工作环境
	 */
	public RequestPhase getRequestPhase() {
		return requestPhase;
	}
	/**
	 * 返回当前的编解码场景
	 */
	public CodecScene getScene() {
		return scene;
	}
	@Override
	public int hashCode() {
		return Objects.hash(bean, requestPhase);
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		LocalContext other = (LocalContext) obj;
		return Objects.equals(bean, other.bean) && requestPhase == other.requestPhase;
	}
	private static final LocalContext DEFAULT_CONTEXT = new LocalContext();
	private static final ThreadLocal<LocalContext> LOCAL_CONTEXT = new ThreadLocal<>();
	public static LocalContext getCurrentContext() {
		LocalContext ctx = LOCAL_CONTEXT.get();
		return null == ctx ? DEFAULT_CONTEXT: ctx;
	}
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("LocalContext [bean=").append(bean).append(", requestPhase=").append(requestPhase)
				.append(", scene=").append(scene).append("]");
		return builder.toString();
	}
	/**
	 * 进入序列化/反序列化状态<br>
	 * 由序列化/反序列化器在执行/反序列化之前调用，
	 * 与{@link #exitingEnv()}配合使用，向过滤器内部工作的过滤器激活器{@link com.gitee.l0km.beanfilter.core.Activation}提供工作状态数据
	 * @param bean 当前序列化对象，反序列化时为{@code null}
	 * @param requestPhase 当前工作状态：序列化 OR 反序列
	 * @param scene 编解码场景
	 */
	public static void enteringEnv(Object bean,RequestPhase requestPhase, CodecScene scene) {
		LOCAL_CONTEXT.set(new LocalContext(bean== null ? NULL_OBJECT:bean,requestPhase, scene));
	}
	/**
	 * 退出序列化/反序列化状态<br>
	 * 与{@link #enteringEnv(Object, RequestPhase, CodecScene)}配合使用,在序列化/反序列化结束时调用
	 */
	public static void exitingEnv() {
		LOCAL_CONTEXT.remove();
	}
}
